package com.chj.design.sk;

public class Code14_Singleton2 {

	public static class Singleton01 {
//		饿汉式
//		依赖 JVM类加载机制，保证单例只会被创建1次，
//		即 线程安全 

//		1.JVM在类的初始化阶段(即 在Class被加载后、被线程使用前)，会执行类的初始化
//		2.在执行类的初始化期间，JVM会去获取一个锁。这个锁可以同步多个线程对同一个类的初始化

		// 1. 加载该类时，单例就会自动被创建
		private static Singleton01 ourInstance = new Singleton01();

		// 2. 构造函数 设置为 私有权限
		// 原因：禁止他人创建实例
		private Singleton01() {
		}

		// 3. 通过调用静态方法获得创建的单例
		public static Singleton01 newInstance() {
			return ourInstance;
		}
	}

	public static class Singleton02 {
//		懒汉式
		// 1. 创建静态内部类
		private static class Singleton2 {
			// 在静态内部类里创建单例
			private static Singleton02 ourInstance = new Singleton02();
		}

		// 私有构造函数
		private Singleton02() {
		}

		// 延迟加载、按需创建
		public static Singleton02 newInstance() {
			return Singleton2.ourInstance;
		}

	}
//	懒汉式
	// 调用过程说明：
	// 1. 外部调用类的newInstance()
	// 2. 自动调用Singleton2.ourInstance
	// 2.1 此时单例类Singleton2得到初始化
	// 2.2 而该类在装载 & 被初始化时，会初始化它的静态域，从而创建单例；
	// 2.3 由于是静态域，因此只会JVM只会加载1遍，Java虚拟机保证了线程安全性
	// 3. 最终只创建1个单例

	// https://www.cnblogs.com/xz816111/p/8470048.html
	// 双重校验锁（懒汉式的改进）
	public static class DCLSingleton {
		private static volatile DCLSingleton dclSingleton;

		private DCLSingleton() {
		}

		public static DCLSingleton getInstance() {
			// 定义这个局部变量可以提高大约25%的性能🚀 依据:Joshua Bloch "Effective Java, Second Edition", p.
			// 283-284
			DCLSingleton current = dclSingleton;
			// 1️⃣ 第一次检查
			if (dclSingleton == null) {
				// 🔒此时为了保证线程安全,我们不清楚其他线程是否已经实例化该对象,所以将类上锁达到互斥效果
				synchronized (DCLSingleton.class) {
					/*
					 * 再次将实例分配给局部变量并检查它是否由其他某个线程初始化 当前线程被阻止进入锁定区域。 如果它已初始化，那么我们可以
					 * 返回先前创建的实例，就像上面检查对象是否为空一样。
					 */
					current = dclSingleton;
					// 2️⃣ 第二次检查
					if (dclSingleton == null) {
						// 如果此时该类还没有被实例化,那么我们就可以安全的实例化一个单例的该对象实例.
						current = dclSingleton = new DCLSingleton();
					}
				}
			}
			return current;
		}
	}
}
